<?php
/**
 * 有赞授权相关
 */

namespace App\Http\Controllers\Youzan;

use App\Http\Controllers\ApiController;
use App\Http\Requests\YouZan\OAuthRequest;
use App\Models\Concerns\YouzanAuthorizerable;
use App\Models\Customer\Customer;
use App\Models\Panx\Product;
use App\Models\Store\Store;
use App\Models\Youzan\YouzanAuthorizer;
use App\Services\Repositories\Product\ProductRepository;
use App\Services\Utils\Transaction;
use App\Services\Youzan\AppFactory;
use App\Services\Youzan\AuthorizerableService;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Http\Request;


class OAuthController extends ApiController
{
    const STATE_SEPARATOR = '-';  // oauth授权state自定义参数分割符，用来分割商家/店铺ID

    const PRE_AUTH_CALLBACK_ROUTE = 'youzan.authorize_callback';

    const AUTHORIZATION_PROMPT_PAGE = "/web-admin/?customer_id=%s&store_id=%s&auth_succeed=%d#/authorize-status";

    /**
     * @var \Hanson\Youzan\Youzan
     */
    protected $youzan;

    public function __construct()
    {
        $this->youzan = AppFactory::youzan();
    }

    /**
     * 重定向到店铺授权地址
     *
     * @param OAuthRequest $request
     * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
     * @throws \Exception
     */
    public function redirectToAuthorize(OAuthRequest $request)
    {
        // 授权的customer_id 或 store_id
        $customer_id = $request->customer_id ?: 0;
        $store_id = $request->store_id ?: 0;

        $state = $customer_id . self::STATE_SEPARATOR . $store_id;

        // 获取授权 URL
        $url = $this->youzan->pre_auth->authorizationUrl($state);

        return redirect($url);
    }


    /**
     * 授权回调，获取店铺授权信息
     *
     * @example
     *  返回链接格式  http://mirror.me/youzan/authorize-callback?code=0c84ee9bf4223defb0dfe1b5262741c5&state=test_auth
     *
     * @param Request $request
     * @return string
     * @throws \Exception
     */
    public function authorizeCallback(Request $request)
    {
        $auth_succeed = 0;

        $state_array = explode(self::STATE_SEPARATOR, $request->state);

        list($customer_id, $store_id) = $state_array;

        try {
            // 获取授权的 customer 或 store
            $customer_or_store = $this->findAuthorizerableModel($customer_id, $store_id);

            /**
             * @see Mock::accessToken() - 获取此次授权的 token信息
             */
            $token_info = $this->getAccessToken();

            /**
             * @see Mock::shop() - 获取有赞店铺的基础信息
             * @see Mock::basicShop() - 获取有赞店铺的基本信息
             */
            $shop = $this->getShop($token_info['access_token']);

            $youzan_author = $this->updateOrCreateAuthorizer($shop, $token_info, $customer_or_store);

            $auth_succeed = $youzan_author ? 1 : 0;

        } catch (\Exception $e) {
            logger('【有赞授权回调错误】');
            logger($e->getMessage());
        }

        return redirect(sprintf(self::AUTHORIZATION_PROMPT_PAGE, $customer_id, $store_id, $auth_succeed));
    }

    /**
     * @param $shop
     * @param $token_info
     * @param YouzanAuthorizerable|Customer|Store $customer_or_store
     *
     * @return mixed
     * @throws \Exception
     */
    private function updateOrCreateAuthorizer(array $shop, array $token_info,
                                              YouzanAuthorizerable $customer_or_store): YouzanAuthorizer
    {
        return Transaction::handle(function () use ($shop, $token_info, $customer_or_store) {
            /** @var YouzanAuthorizer $youzan_auth */
            $youzan_auth = (new YouzanAuthorizer)->updateOrCreate(
                ['youzan_store_id' => $shop['id']],
                [
                    'access_token'       => $token_info['access_token'],
                    'expires_in'         => $token_info['expires_in'],
                    'refresh_token'      => $token_info['refresh_token'],
                    'scope'              => $token_info['scope'],
                    'token_type'         => $token_info['token_type'],
                    'youzan_store_name'  => $shop['name'],
                    'youzan_store_logo'  => $shop['logo'],
                    'youzan_store_intro' => $shop['intro'],
                    'url'                => $shop['url'],
                    'physical_url'       => $shop['physical_url'],
                    'cert_type'          => $shop['cert_type'],
                    'expired_at'         => now()->addSecond($token_info['expires_in']),
                ]
            );

            // 删除原来有赞商品和订单
            (new AuthorizerableService)->deleteYouzanProductsAndOrders($customer_or_store, $shop['id']);

            $customer_or_store->update(['youzan_authorizer_id' => $youzan_auth->id]);

            return $youzan_auth;
        });
    }

    /**
     * @param $customer_id
     * @param $store_id
     * @return YouzanAuthorizerable
     */
    private function findAuthorizerableModel(int $customer_id, int $store_id): YouzanAuthorizerable
    {
        if ($customer_id) {
            $authorizerable = Customer::find($customer_id);
        } else {
            $authorizerable = Store::find($store_id);
        }

        return $authorizerable;
    }

    /**
     * @param $access_token
     * @return array
     */
    private function getShop($access_token)
    {
        $youzan = $this->youzan->oauth->createAuthorization($access_token);

        $shop = $youzan->request(AppFactory::YOUZAN_SHOP_GET);
        $basic_shop = $youzan->request(AppFactory::YOUZAN_SHOP_BASIC_GET);

        return array_merge($shop, $basic_shop);
    }

    /**
     * @return mixed
     */
    private function getAccessToken()
    {
        $token = $this->youzan->pre_auth->getAccessToken();

        return $token;
    }


}
